//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Web.Caching;
using System.Xml;
using CommunityServer.Configuration;


namespace CommunityServer.Components 
{

	/// <summary>
	/// Manages the Links in the application
	/// </summary>
	public class Links {
		private Links() {
			// static class
		}

		#region Management

		/// <summary>
		/// Adds the given link to the database.
		/// </summary>
		public static void CreateLink( Link link ) {

		    CommonDataProvider dp = CommonDataProvider.Instance();

			Format(link);

			link.LinkID = dp.CreateLink( link );
			
			// Make sure the addition was successful
			if( link.LinkID > 0 ) {
				Hashtable links = CSCache.Get( CacheKey( link.LinkCategoryID ) ) as Hashtable;
				if( links != null ) {
					links.Add( link.LinkID, link );
				}
			} else {
				throw new CSException( CSExceptionType.UnknownError );
			}
		}

		private static void Format(Link link)
		{
			if(!Globals.IsNullorEmpty(link.Title))
			{
				if(CSContext.Current.SiteSettings.EnableCensorship)
				{
					link.Title = Transforms.CensorPost(link.Title);
					link.Description = Transforms.CensorPost(link.Description);
					link.Rel = Transforms.CensorPost(link.Rel);
				}
				
				link.Title = HtmlScrubber.Clean(link.Title,true,true);
				link.Description = HtmlScrubber.Clean(link.Description,true,true);
				link.Rel = HtmlScrubber.Clean(link.Rel,true,true);
			}
		}

		/// <summary>
		/// Updates the given link to the database.
		/// </summary>
		public static void UpdateLink( Link link ) {
			// Update it in the database


			Format(link);

		    CommonDataProvider dp = CommonDataProvider.Instance();
			dp.UpdateLink( link );

			// cache it
			Hashtable links = CSCache.Get( CacheKey( link.LinkCategoryID ) ) as Hashtable;
			if( links != null ) {
				if( links.ContainsKey( link.LinkID ) ) {
					try {
						links[ link.LinkID ] = link;
					}
					catch{}//not much to do here
				}

			}
		}

		/// <summary>
		/// Deletes the link in the database with the given link and category ids.
		/// </summary>
		public static void DeleteLink( Int32 linkID, Int32 linkCategoryID ) {
		    CommonDataProvider dp = CommonDataProvider.Instance();
			dp.DeleteLink( linkID );
			CSCache.Remove( CacheKey( linkCategoryID ) );
		}

		/// <summary>
		/// Moves the link up or down in a sorted list of the links.
		/// </summary>
		public static void ChangeLinkSortOrder( Int32 linkID, Int32 linkCategoryID, Boolean moveUp ) {
		    CommonDataProvider dp = CommonDataProvider.Instance();
			dp.ChangeLinkSortOrder( linkID, moveUp );
			CSCache.Remove( CacheKey( linkCategoryID ) );
		}

		#endregion

		#region Single Selection

		/// <summary>
		/// Gets the link with the given link and category ids.
		/// </summary>
		public static Link GetLink( Int32 linkID, Int32 linkCategoryID ) {
			return GetLink( linkID, linkCategoryID, false );
		}


		/// <summary>
		/// Gets the link with the given link and category ids.
		/// </summary>
		/// <remarks>
		/// If allowDisabled is false, then the link won't be returned if it is not enabled.
		/// </remarks>
		public static Link GetLink( Int32 linkID, Int32 linkCategoryID, bool allowDisabled ) {
			Hashtable links = GetLinks( linkCategoryID, CSContext.Current, allowDisabled, true );
			
			if( !links.Contains( linkID ) ) {
				throw new CSException(CSExceptionType.ResourceNotFound, "Link not found: " + linkID);
			}
			
			return (Link)links[linkID];
		}

		#endregion

		#region Multiple Selection

		/// <summary>
		/// Gets all the enabled links in the given category.
		/// </summary>
		public static ArrayList GetLinks( Int32 linkCategoryID ) {
			return GetLinks( linkCategoryID, false, true );
		}

		/// <summary>
		/// Gets all the links in the given category.
		/// </summary>
		public static ArrayList GetLinks( Int32 linkCategoryID, Boolean allowDisabled ) {
			return GetLinks( linkCategoryID, allowDisabled, true );
		}


		/// <summary>
		/// Gets all the links in the given category.
		/// </summary>
		public static ArrayList GetLinks( Int32 linkCategoryID, Boolean allowDisabled, Boolean cacheable ) {
		    CSContext csContext = CSContext.Current;
			ArrayList links = new ArrayList();

			// Get the Albums as a hashtable
			Hashtable linkTable = GetLinks( linkCategoryID, csContext, allowDisabled, cacheable );

			// Convert the hashtable to an arraylist
			foreach(Link link in linkTable.Values) {
				links.Add( link );
			}

			// Sort the categories
			
            links.Sort();

			return links;
		}

		/// <summary>
		/// Gets all the links in the given category.
		/// </summary>
		public static Hashtable GetLinks( Int32 linkCategoryID, CSContext csContext, Boolean allowDisabled, Boolean cacheable ) {

			string cacheKey = CacheKey( linkCategoryID );

#if DEBUG_NOCACHE
			cacheable = false;
#endif

			Hashtable links = CSCache.Get(cacheKey) as Hashtable;

			// Ensure it's not in the cache
			if ((!cacheable) && (links != null)) {
				CSCache.Remove(cacheKey);
			}

			// Get the categories
			if( links == null ) {
			    CommonDataProvider dp = CommonDataProvider.Instance();
			
				links = dp.GetLinks( linkCategoryID );

				// Cache if we can
				if ( cacheable ) {
					CSCache.Insert( cacheKey, links, 3 * CSCache.MinuteFactor );
				}
			}

			// Should we return all of them?
			if( allowDisabled ) {
				return links;
			}
			
			// Filter out the disabled categories
			Hashtable enabledLinks = new Hashtable();
			foreach( Link link in links.Values ) {
				if( link.IsEnabled ) {
					enabledLinks.Add( link.LinkID, link );
				}
			}
			return enabledLinks;
		}

		#endregion

		public static Hashtable GetLinkRelValues(string language)
		{
			CSContext csContext = CSContext.Current;
			string cacheKey = "LinkRelationsResources-" + language;
			Hashtable relations = CSCache.Get(cacheKey) as Hashtable;

			if(relations == null)
			{
				string filePath = csContext.Context.Server.MapPath(String.Format("~{0}/Languages/{1}/metadata/LinkRelations.xml", CSConfiguration.GetConfig().FilesPath, language));
				CacheDependency dp = new CacheDependency(filePath);
				XmlDocument d = new XmlDocument();
				relations = new Hashtable();

				try 
				{
					d.Load( filePath );
				} 
				catch 
				{
					return null;
				}

				foreach(XmlNode n in d.SelectSingleNode("root").ChildNodes) 
				{
					if (n.NodeType != XmlNodeType.Comment) 
					{
						relations.Add(n.Attributes.GetNamedItem("value").Value, n.InnerText);
					}
				}
				CSCache.Max(cacheKey, relations, dp);
			}

			return relations;
		}

		private static string CacheKey( Int32 linkCategoryID ) {
			return String.Format( "BlogLinksCacheKey:{0}", linkCategoryID );
		}

	}
}
